<?php
namespace App\Services;

use App\Api\Models\StorageBatchModel;
use App\Models\InStorageLogModel;
use App\Models\LogInstorageModel;
use App\Models\LogOutPackageModel;
use App\Models\LogOutstorageModel;
use App\Models\LogPackageContentModel;
use App\Models\LogPackageModel;
use App\Models\StorageManageModel;
use App\Models\UserModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use App\V3\Api\Models\SerialNumberModel;

class LogService
{
    //撤销直接入库
    static public function cancelDirectInstorage($data)
    {
        $logInstorageInfo = LogInstorageModel::where([
            'id' => $data['id'],
            'main_id' => $data['main_id']
        ])->first();

        if(empty($logInstorageInfo)) {
            return ['code' => 1, 'msg' => '无效操作记录', 'data' => ''];
        }

        if($logInstorageInfo['type'] != 2) {
            return ['code' => 1, 'msg' => '非直接入库，无法完成撤销', 'data' => ''];
        }

        if($logInstorageInfo['is_cancel'] == 1) {
            return ['code' => 1, 'msg' => '已撤销，无法重复操作', 'data' => ''];
        }

        $storageManageInfo = StorageManageModel::where([
            'id' => $logInstorageInfo['curr_storage_manage_id'],
            'delete_flag' => 0
        ])->first();

        $storageBatchInfo = [];

        if(!empty($logInstorageInfo['batch_id'])){

        $storageBatchInfo = StorageBatchModel::where('id',$logInstorageInfo['batch_id'])->first();

        }

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '记录中商品已被删除，无法完成撤销', 'data' => ''];
        }

        if($logInstorageInfo['operate_num'] > $storageManageInfo['in_storage_num']) {
            return ['code' => 1, 'msg' => '当前商品库存数不足(实际库存:'.$storageManageInfo['in_storage_num'].',撤销数量:'.$logInstorageInfo['operate_num'].')，无法完成撤销', 'data' => ''];
        }

        if($storageManageInfo['virtual_storage_num'] > 0) {
            if($logInstorageInfo['operate_num'] > $storageManageInfo['virtual_storage_num']) {
                return ['code' => 1, 'msg' => '当前商品虚拟库存数不足(实际库存:'.$storageManageInfo['virtual_storage_num'].',撤销数量:'.$logInstorageInfo['operate_num'].')，无法完成撤销', 'data' => ''];
            }
        }

        DB::beginTransaction();

        try {
            LogInstorageModel::where('id', $data['id'])->update(['is_cancel' => 1]);
            if($storageManageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where('id', $logInstorageInfo['curr_storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$logInstorageInfo['operate_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$logInstorageInfo['operate_num'])
                    ]);
            }
            else {
                StorageManageModel::where('id', $logInstorageInfo['curr_storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$logInstorageInfo['operate_num']),
                    ]);
            }
            if(!empty($logInstorageInfo['batch_id']) && !empty($storageBatchInfo)){

                if($logInstorageInfo['operate_num'] <= $storageBatchInfo['batch_left_num']) {

                    $num = $storageBatchInfo['batch_left_num']- $logInstorageInfo['operate_num'];

                    StorageBatchModel::where('id',$logInstorageInfo['batch_id'])->update(['batch_left_num' => $num]);
                }
            }

            if(!empty($logInstorageInfo['serial_number'])){

                $serialNumberList = explode(',', $logInstorageInfo['serial_number']);
                $scondition['status'] = 1;
                $scondition['goods_id'] = $logInstorageInfo['materiel_type_id'];
                SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->delete();

//                SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->update(['status'=>0]);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('撤销直接入库:'.var_export($e->getMessage(), true));
        }
    }

    //操作记录列表
    static public function list($data, $status, $userId)
    {
        //DB::enableQueryLog();
        switch($data['type']) {
            //入库
            case 0:
                $result = SELF::instorageList($data, $status, $userId);
                break;
            //出库
            case 1:
                $result = SELF::outstorageList($data, $status, $userId);
                break;
            //套餐出库
            case 2:
                $result = SELF::packageOutstorageList($data, $status, $userId);
                break;
        }
       // $sql = DB::getQueryLog();
        //var_dump($sql);die;
        return $result;
    }

    //入库操作记录
    static private function instorageList($data, $status, $userId)
    {
        $query = LogInstorageModel::select(
            'a.id',
            'a.type',
            'f.storage_name',
            'f.storage_address',
            'g.storage_name as last_storage_name',
            'g.storage_address as last_storage_address',
//            'a.materiel_class_name',
//            'a.materiel_class_no',
            'e.materiel_name',
            'e.type_name',
            'e.materiel_no',
            'a.operate_num',
            'a.last_storage_num',
            'a.next_storage_num',
            'a.materiel_mean_cost',
            'a.remark',
            'a.is_cancel',
            'a.in_storage_time',
            'a.purchase_no',
            'c.class_name',
            'c.class_no',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'd.username',
            'd.nickname'
        )
            ->from('log_instorage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
            ->leftJoin('admin as d', 'd.id', '=', 'a.user_id')
            ->leftJoin('materiel_type as e', 'e.id', '=', 'a.materiel_type_id')
            ->leftJoin('storage as f', 'f.id', '=', 'a.storage_id')
            ->leftJoin('storage as g', 'g.id', '=', 'a.last_storage_id')
            ->where('a.delete_flag', 0)
            ->where($userId)
            ->where('a.is_cancel', $status);

        if($data['materiel_class_id'] != 0) {
            $query->where('a.materiel_class_id', $data['materiel_class_id']);
        }

        $keyword = empty($data['keyword'])?'':$data['keyword'];

        if(!empty($data['start_time'])) {
            $startTimeArr = explode(' ', $data['start_time']);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($data['end_time'])) {
            $endTimeArr = explode(' ', $data['end_time']);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('in_storage_time', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query->where('in_storage_time', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query->where('in_storage_time', '<=', $endTime);
        }

        return $query->where(function($query) use ($keyword, $data) {
            $query->orWhere('b.class_name', 'like', '%'.$keyword.'%');
            $query->orWhere('b.class_no', 'like', '%'.$keyword.'%');
            $query->orWhere('c.class_name', 'like', '%'.$keyword.'%');
            $query->orWhere('c.class_no', 'like', '%'.$keyword.'%');
            $query->orWhere('e.materiel_name', 'like', '%'.$keyword.'%');
            $query->orWhere('e.type_name', 'like', '%'.$keyword.'%');
            $query->orWhere('e.materiel_no', 'like', '%'.$keyword.'%');
            $query->orWhere('f.storage_name', 'like', '%'.$keyword.'%');
            $query->orWhere('g.storage_name', 'like', '%'.$keyword.'%');
            $query->orWhere('allocate_no', 'like', '%'.$keyword.'%');

            if($data['type'] == 0) {
                $query->orWhere('purchase_no', 'like', '%'.$keyword.'%');
            }
        })
            ->orderBy('a.id', 'desc')
            ->paginate($data['pageSize'],['*'], '',$data['currentPage']);
    }

    //出库操作记录
    static private function outstorageList($data, $status, $userId)
    {
        $query = LogOutstorageModel::select(
            'a.id',
            'a.type',
            'f.storage_name',
            'f.storage_address',
            'g.storage_name as next_storage_name',
            'g.storage_address as next_storage_address',
//            'a.materiel_class_name',
//            'a.materiel_class_no',
            'e.materiel_name',
            'e.type_name',
            'e.materiel_no',
            'a.operate_num',
            'a.last_storage_num',
            'a.next_storage_num',
            'a.materiel_mean_cost',
            'a.remark',
            'a.is_cancel',
            'a.out_storage_time',
            'c.class_name',
            'c.class_no',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'd.username',
            'd.nickname'
        )
            ->from('log_outstorage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
            ->leftJoin('admin as d', 'd.id', '=', 'a.user_id')
            ->leftJoin('materiel_type as e', 'e.id', '=', 'a.materiel_type_id')
            ->leftJoin('storage as f', 'f.id', '=', 'a.storage_id')
            ->leftJoin('storage as g', 'g.id', '=', 'a.next_storage_id')
            ->where('a.delete_flag', 0)
            ->where($userId)
            ->where('is_cancel', $status);

        if($data['materiel_class_id'] != 0) {
            $query->where('a.materiel_class_id', $data['materiel_class_id']);
        }

        $keyword = empty($data['keyword'])?'':$data['keyword'];

        if(!empty($data['start_time'])) {
            $startTimeArr = explode(' ', $data['start_time']);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($data['end_time'])) {
            $endTimeArr = explode(' ', $data['end_time']);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('out_storage_time', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query->where('out_storage_time', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query->where('out_storage_time', '<=', $endTime);
        }

        return $query->where(function($query) use ($keyword, $data) {
            $query->orWhere('b.class_name', 'like', '%'.$keyword.'%');
            $query->orWhere('b.class_no', 'like', '%'.$keyword.'%');
            $query->orWhere('c.class_name', 'like', '%'.$keyword.'%');
            $query->orWhere('c.class_no', 'like', '%'.$keyword.'%');
            $query->orWhere('e.materiel_name', 'like', '%'.$keyword.'%');
            $query->orWhere('e.type_name', 'like', '%'.$keyword.'%');
            $query->orWhere('e.materiel_no', 'like', '%'.$keyword.'%');
            $query->orWhere('f.storage_name', 'like', '%'.$keyword.'%');
            $query->orWhere('g.storage_name', 'like', '%'.$keyword.'%');
            $query->orWhere('allocate_no', 'like', '%'.$keyword.'%');

            if($data['type'] == 0) {
                $query->orWhere('purchase_no', 'like', '%'.$keyword.'%');
            }
        })
            ->groupBy('out_storage_time')
            ->orderBy('a.id', 'desc')
            ->paginate($data['pageSize'],['*'], '',$data['currentPage']);
    }

    static public function packageOutstorageList($data, $status, $userId)
    {
        $keyword = empty($data['keyword'])?'':$data['keyword'];

        $query = LogPackageModel::select(
            'a.id',
            'package_name',
            'num',
            'a.remark',
            'a.is_cancel',
            'a.created_at',
            'username',
            'nickname'
        )
            ->from('log_package as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->leftJoin('log_package_content as c', 'c.log_package_id', '=', 'a.id')
            ->where('a.delete_flag', 0)
            ->where($userId)
            ->where('a.is_cancel', $status);

        if(!empty($data['start_time'])) {
            $startTimeArr = explode(' ', $data['start_time']);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($data['end_time'])) {
            $endTimeArr = explode(' ', $data['end_time']);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query->whereBetween('a.created_at', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query->where('a.created_at', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query->where('a.created_at', '<=', $endTime);
        }

        $query->where(function($query) use ($keyword) {
            $query->orWhere('package_name', 'like', '%'.$keyword.'%');
            $query->orWhere('materiel_name', 'like', '%'.$keyword.'%');
            $query->orWhere('type_name', 'like', '%'.$keyword.'%');
            $query->orWhere('materiel_no', 'like', '%'.$keyword.'%');
            $query->orWhere('materiel_class_name', 'like', '%'.$keyword.'%');
            $query->orWhere('materiel_class_no', 'like', '%'.$keyword.'%');
        });

        return $query->orderBy('a.id', 'desc')
            ->groupBy('a.id')
            ->paginate($data['pageSize'],['*'], '',$data['currentPage']);
    }

    //操作记录详细
    static public function detail($data)
    {
        switch($data['type']) {
            case 0:
                $result = SELF::logInstorageDetail($data);
                break;
            case 1:
                $result = SELF::logOutstorageDetail($data);
                break;
            case 2:
                $result = SELF::logPackageContentDetail($data);
                break;
        }

        return $result;
    }

    static private function logInstorageDetail($data)
    {
        $info = LogInstorageModel::select(
            'a.id',
            'a.type',
            'f.storage_name as last_storage_name',
            'f.storage_address as last_storage_address',
            'e.storage_name',
            'e.storage_address',
//            'a.materiel_class_name',
//            'a.materiel_class_no',
            'g.materiel_name',
            'g.type_name',
            'g.materiel_no',
            'a.operate_num',
            'a.last_storage_num',
            'a.next_storage_num',
            'a.materiel_mean_cost',
            'a.all_id_type',
            'a.remark',
            'a.is_cancel',
            'a.in_storage_time',
            'a.purchase_no',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'c.class_name',
            'c.class_no',
            'd.username',
            'd.nickname',
            'serial_number',
            'i.batch_no'
        )
        ->from('log_instorage as a')
        ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
        ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
        ->leftJoin('admin as d', 'd.id', '=', 'a.user_id')
        ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
        ->leftJoin('storage as f', 'f.id', '=', 'a.last_storage_id')
        ->leftJoin('materiel_type as g', 'g.id', '=', 'a.materiel_type_id')
        ->leftJoin('storage_batch as i','i.id','=','a.batch_id')
        ->where([
            'a.id' => $data['id'],
        ])
        ->first();

        if(!empty($info['serial_number'])){
            $info['serial_number'] = explode(',', $info['serial_number']);
        }else{
            $info['serial_number'] = [];
        }
        return $info;
    }

    //出库操作记录详细
    static private function logOutstorageDetail($data)
    {
        $info = LogOutstorageModel::select(
                'a.id',
                'a.type',
                'f.storage_name as next_storage_name',
                'f.storage_address as next_storage_address',
                'e.storage_name',
                'e.storage_address',
                'a.materiel_type_id as goods_id',
//                'a.materiel_class_no',
                'g.materiel_name',
                'g.type_name',
                'g.materiel_no',
                'a.operate_num',
                'a.last_storage_num',
                'a.next_storage_num',
                'a.materiel_mean_cost',
                'a.remark',
                'a.all_id_type',
                'a.is_cancel',
                'a.out_storage_time',
                'b.class_name as materiel_class_name',
                'b.class_no as materiel_class_no',
                'c.class_name',
                'c.class_no',
                'd.username',
                'd.nickname',
                'a.serial_number',
                'i.batch_no',
            'a.shelf_id as sh_id',
            'a.location_id as lo_id',
            'a.out_storage_time'
            )
            ->from('log_outstorage as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
            ->leftJoin('admin as d', 'd.id', '=', 'a.user_id')
            ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
            ->leftJoin('storage as f', 'f.id', '=', 'a.next_storage_id')
            ->leftJoin('materiel_type as g', 'g.id', '=', 'a.materiel_type_id')
            ->leftJoin('storage_batch as i','i.id','=','a.storage_batch_id')
            ->where([
                'a.id' => $data['id']
            ])
            ->first()->toArray();

            if(!empty($info['serial_number'])){
                $loCondition= [];
                $serialArr = [];
                $loCondition['shelf_id'] = $info['sh_id'];
                $loCondition['location_id'] = $info['lo_id'];
                $loCondition['out_storage_time'] = strtotime($info['out_storage_time']);
                $loCondition['materiel_type_id'] = $info['goods_id'];
                $loList = LogOutstorageModel::select('serial_number')->where($loCondition)->get()->toArray();

                if(!empty($loList)){
                    foreach($loList as $key=>$val){
                        if(!empty($val['serial_number'])){
                            $serialData = explode(',', $val['serial_number']);
                            if(is_array($serialData)){
                                foreach($serialData as $sKey=>$sVal){
                                    $serialArr[] = $sVal;
                                }
                            }else{
                            $serialArr[] = $val['serial_number'];
                            }
                        }
                    }
                }
                $info['serial_number'] = $serialArr;
            }else{
                $info['serial_number'] = [];
            }
            return $info;
    }

    //套餐出库记录详细
    static public function logPackageContentDetail($data)
    {
        $datas = LogPackageModel::select(
            'a.id',
            'c.package_name',
            'num',
            'remark',
            'a.created_at',
            'username',
            'nickname',
            'is_cancel'
        )
            ->from('log_package as a')
            ->leftJoin('admin as b', 'b.id', '=', 'a.user_id')
            ->with('hasManyContent', function($query) {
                $query->select(
                    'log_package_content.id',
                    'log_package_id',
                    'a.storage_name',
                    'a.storage_address',
                    'b.class_name as second_class_name',
                    'c.class_name as first_class_name',
                    'd.materiel_name',
                    'd.type_name',
                    'operate_num',
                    'e.in_storage_num',
                    'log_package_content.serial_number',
                    'i.batch_no'
                )
                ->leftJoin('storage as a', 'a.id', '=', 'log_package_content.storage_id')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'log_package_content.materiel_class_id')
                ->leftJoin('materiel_class as c', 'b.parent_id', '=', 'c.id')
                ->leftJoin('materiel_type as d', 'd.id', '=', 'log_package_content.materiel_type_id')
                ->leftJoin('storage_manage as e', 'e.id', '=', 'log_package_content.out_storage_manage_id')
                ->leftJoin('storage_batch as i','i.id','=','log_package_content.storage_batch_id');
            })
            ->leftJoin('package as c', 'c.id', '=', 'a.package_id')
            ->where('a.id', $data['id'])
            ->get()->toArray();

            if(!empty($datas[0]['has_many_content'])){
                foreach ($datas[0]['has_many_content'] as &$v){
                    if(!empty($v['serial_number'])){
                        $v['serial_number'] = explode(',', $v['serial_number']);
                    }else{
                        $v['serial_number']=[];
                    }
                }
            }

        $arr['id'] = $datas[0]['id'];
        $arr['package_name'] = $datas[0]['package_name'];
        $arr['num'] = $datas[0]['num'];
        $arr['remark'] = $datas[0]['remark'];
        $arr['created_at'] = $datas[0]['created_at'];
        $arr['username'] = $datas[0]['username'];
        $arr['nickname'] = $datas[0]['nickname'];
        $arr['is_cancel'] = $datas[0]['is_cancel'];
        $arr['content'] = $datas[0]['has_many_content'];

        return $arr;
    }

    /**
     *调拨撤销
     * @param $data['type] 操作日志类型;0:调入侧撤销;1:调出侧撤销;
     */
    static public function cancelAllocate($data)
    {
        switch($data['type']) {
            case 0:
                    $result = SELF::cancelAllocateIn($data);
                break;
            case 1:
                    $result = SELF::cancelAllocateOut($data);
                break;
        }

        return $result;
    }

    //调拨-调入侧撤销
    static private function cancelAllocateIn($data)
    {
        $logInfo = LogInstorageModel::where('id', $data['id'])->first();

        if($logInfo['type'] != 1) {
            return ['code' => 1, 'msg' => '非调拨产生的记录，无法完成撤销', 'data' => ""];
        }

        if($logInfo['is_cancel'] == 1) {
            return ['code' => 1, 'msg' => '无法重复撤销', 'data' => ""];
        }

        //调入库存商品信息
        $nextStorageMnageInfo = StorageManageModel::where([
            'id' => $logInfo['curr_storage_manage_id'],
            'delete_flag' => 0
        ])->first();

        if(empty($lastStorageManageInfo)) {
            return ['code' => 1, 'msg' => '记录中商品已被删除，无法完成撤销', 'data' => ""];
        }

        if(empty($nextStorageMnageInfo)) {
            return ['code' => 1, 'msg' => '记录中商品已被删除，无法完成撤销', 'data' => ""];
        }

        if($logInfo['operate_num'] > $nextStorageMnageInfo['in_storage_num']) {
            return ['code' => 1, 'msg' => '库存不足，无法完成撤销', 'data' => ""];
        }

        $storageBatchInfo = [];

        if(!empty($logInfo['batch_id'])){

            $storageBatchInfo = StorageBatchModel::where('id',$logInfo['batch_id'])->first();

        }


        DB::beginTransaction();
        try {
            //扣除调入的数量

            if($nextStorageMnageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where([
                    'id' => $logInfo['curr_storage_manage_id']
                ])->update([
                    'in_storage_num' => DB::raw('in_storage_num - '.$logInfo['operate_num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num - '.$logInfo['operate_num']),
                ]);
            }
            else {
                StorageManageModel::where([
                    'id' => $logInfo['curr_storage_manage_id']
                ])->update([
                    'in_storage_num' => DB::raw('in_storage_num - '.$logInfo['operate_num']),
                ]);
            }

            //还原调出库存商品数量
            StorageManageModel::where([
                'id' => $logInfo['last_storage_manage_id']
            ])
                ->update([
                    'in_storage_num' => DB::raw('in_storage_num + '.$logInfo['operate_num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num + '.$logInfo['operate_num']),
                    'delete_flag' => 0
                ]);

            //变成撤销状态
            LogInstorageModel::where('id', $data['id'])->update(['is_cancel' => 1]);

            //变更调出侧记录撤销状态
            LogOutstorageModel::where([
                'curr_storage_manage_id' => $logInfo['last_storage_manage_id'],
                'out_storage_time' => strtotime($logInfo['in_storage_time']),
                'next_storage_manage_id' => $logInfo['curr_storage_manage_id']
            ])->update(['is_cancel' => 1]);

            if(!empty($logInfo['batch_id']) && !empty($storageBatchInfo)){

                if($logInfo['operate_num'] <= $storageBatchInfo['batch_left_num']) {

                    $num = $storageBatchInfo['batch_left_num']- $logInfo['operate_num'];

                    StorageBatchModel::where('id',$logInfo['batch_id'])->update(['batch_left_num' => $num]);
                }
            }

            if(!empty($logInfo['serial_number'])){

                $serialNumberList = explode(',', $logInfo['serial_number']);
                $scondition['status'] = 1;
                $scondition['goods_id'] = $logInfo['materiel_type_id'];


                SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->update(['status'=>0]);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('撤销-调入侧发生异常:'.var_export($e->getMessage(), true));
        }
    }

    //调拨-调入侧撤销 decrement
    static private function cancelAllocateOut($data)
    {
        //出库记录信息
        $logInfo = LogOutstorageModel::where('id', $data['id'])->first();

        if($logInfo['type'] != 1) {
            return ['code' => 1, 'msg' => '非调拨产生的记录，无法完成撤销', 'data' => 0];
        }

        if($logInfo['is_cancel'] == 1) {
            return ['code' => 1, 'msg' => '无法重复撤销', 'data' => ""];
        }

        //调入库存商品信息
        $nextStorageMnageInfo = StorageManageModel::where([
            'id' => $logInfo['next_storage_manage_id'],
            'delete_flag' => 0
        ])->first();

        if(empty($nextStorageMnageInfo)) {
            return ['code' => 1, 'msg' => '记录中商品已被删除，无法完成撤销', 'data' => ""];
        }

        if($logInfo['operate_num'] > $nextStorageMnageInfo['in_storage_num']) {
            return ['code' => 1, 'msg' => '库存不足，无法完成撤销', 'data' => ""];
        }

        $storageBatchInfo = [];

        if(!empty($logInfo['storage_batch_id'])){

            $storageBatchInfo = StorageBatchModel::where('id',$logInfo['storage_batch_id'])->first();

        }

        DB::beginTransaction();

        try {
            //变更调拨出库撤销状态
            LogOutstorageModel::where('id', $data['id'])->update(['is_cancel' => 1]);

            //变更调入侧记录撤销状态
            LogInstorageModel::where([
                'last_storage_manage_id' => $logInfo['curr_storage_manage_id'],
                'in_storage_time' => strtotime($logInfo['out_storage_time']),
                'curr_storage_manage_id' => $logInfo['next_storage_manage_id']
            ])->update(['is_cancel' => 1]);

            //扣除调入的数量
            StorageManageModel::where([
                'id' => $logInfo['next_storage_manage_id']
            ])->decrement('in_storage_num', $logInfo['operate_num']);

            //还原调出库存商品数量
            StorageManageModel::where([
                'id' => $logInfo['curr_storage_manage_id']
            ])->increment('in_storage_num', $logInfo['operate_num'], [
                'delete_flag' => 0
            ]);

            if(!empty($logInfo['storage_batch_id']) && !empty($storageBatchInfo)){

                    $num = $storageBatchInfo['batch_left_num']+ $logInfo['operate_num'];

                    StorageBatchModel::where('id',$logInstorageInfo['storage_batch_id'])->update(['batch_left_num' => $num]);

            }

            if(!empty($logInfo['serial_number'])){

                $serialNumberList = explode(',', $logInfo['serial_number']);
                $scondition['status'] = 1;
                $scondition['goods_id'] = $logInfo['materiel_type_id'];

                SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->update(['status'=>0]);
            }



            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('撤销-调出侧发生异常:'.var_export($e->getMessage(), true));
        }
    }

    //撤销套餐出库
    static public function cancelPackage($data)
    {
        $packageInfo = LogPackageModel::where('id', $data['id'])->first();

        if($packageInfo['is_cancel'] == 1) {
            return ['code' => 1, 'msg' => '无法重复撤销', 'data' => ""];
        }

        $packageContentInfo = LogPackageContentModel::where('log_package_id', $data['id'])->get()->toArray();
        DB::beginTransaction();

        try {
            foreach($packageContentInfo as $value) {
                $result = StorageManageModel::where('id', $value['out_storage_manage_id'])->first();

                StorageManageModel::where('id', $value['out_storage_manage_id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + '.$value['operate_num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num + '.$value['operate_num']),
                        'delete_flag' => 0
                    ]);

                if($value['storage_batch_id'] != 0) {
                    StorageBatchModel::where('id', $value['storage_batch_id'])
                        ->increment('batch_left_num', $value['operate_num']);
                }

                if(!empty($value['serial_number'])){

                    $serialNumberList = explode(',', $value['serial_number']);
                    $scondition['status'] = 0;
                    $scondition['goods_id'] = $value['materiel_type_id'];


                    SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->update(['status'=>1]);
                }
            }

            LogPackageModel::where('id', $data['id'])->update(['is_cancel' => 1]);
            LogOutPackageModel::where(['all_id_type' => 3, 'all_id' => $data['id']])->update(['is_cancel' => 1]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('撤销-套餐出库:'.var_export($e->getMessage(), true));
        }
    }

    //撤销-直接出库
    static public function cancelDirectOutstorage($data)
    {
        $logInfo = LogOutstorageModel::where('id', $data['id'])->first();

        if($logInfo['type'] != 2) {
            return ['code' => 1, 'msg' => '非直接出库，无法完成撤销', 'data' => 0];
        }

        if($logInfo['is_cancel'] == 1) {
            return ['code' => 1, 'msg' => '无法重复撤销', 'data' => ""];
        }

        $storageBatchInfo = [];

        if(!empty($logInfo['storage_batch_id'])){

            $storageBatchInfo = StorageBatchModel::where('id',$logInfo['storage_batch_id'])->first();

        }

        DB::beginTransaction();

        try {
            StorageManageModel::where('id', $logInfo['curr_storage_manage_id'])
                ->update([
                    'in_storage_num' => DB::raw('in_storage_num + '.$logInfo['operate_num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num + '.$logInfo['operate_num']),
                    'delete_flag' => 0
                ]);

            LogOutstorageModel::where('id', $data['id'])->update(['is_cancel' => 1]);

            if(!empty($logInfo['storage_batch_id']) && !empty($storageBatchInfo)){

                    $num = $storageBatchInfo['batch_left_num']+ $logInfo['operate_num'];

                    StorageBatchModel::where('id',$logInfo['storage_batch_id'])->update(['batch_left_num' => $num]);
            }

            if(!empty($logInfo['serial_number'])){

                $serialNumberList = explode(',', $logInfo['serial_number']);
                $scondition['status'] = 0;
                $scondition['goods_id'] = $logInfo['materiel_type_id'];


                SerialNumberModel::where($scondition)->whereIn('serial_no',$serialNumberList)->update(['status'=>1]);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('撤销-直接出库:'.var_export($e->getMessage(), true));
        }
    }

    /**
     * 获取旧操作记录列表
     * @param $startTime
     * @param $startTime
     * @param $endTime
     * @param $userType
     * @param $userId
     * @param $mainId
     * @return array
     * @author ソンブ
     * @created_at: 2022/2/9 15:31
     */
    static public function oldLogList($type, $startTime, $endTime, $currPage, $pageSize, $userId, $mainId)
    {
        switch($type) {
            case 0:
                $result = SELF::getOldInLog($startTime, $endTime, $currPage, $pageSize, $userId, $mainId);
                break;
            case 1:
                $result = SELF::getOldOutLog($startTime, $endTime, $currPage, $pageSize, $userId, $mainId);
                break;
        }

        return ['code' => 0, 'msg' => 'success', 'data' => $result];
    }

    static public function getOldInLog($startTime, $endTime, $currPage, $pageSize, $userId, $mainId)
    {
        if($userId == $mainId) {
            $query = InStorageLogModel::select(
                'a.id',
                'a.type',
                'c.class_name as first_class_name',
                'd.class_name as second_class_name',
                'e.type_name',
                'e.materiel_name',
                'f.storage_name',
                'f.storage_address',
                'a.is_cancel',
                'g.nickname',
                'a.account_type',
                'a.oprate_num',
                'b.in_storage_num',
                'a.oprate_time',
            )
                ->from('in_storage_log as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('storage as f', 'f.id', '=', 'b.storage_id')
                ->leftJoin('admin as g', 'g.id', '=', 'a.main_id')
                ->where('a.main_id', $mainId);
        }
        else {
            $userInfo = UserModel::where('new_id', $userId)->first();

            $query = InStorageLogModel::select(
                'a.id',
                'a.type',
                'c.class_name as first_class_name',
                'd.class_name as second_class_name',
                'e.type_name',
                'e.materiel_name',
                'f.storage_name',
                'f.storage_address',
                'a.is_cancel',
                'g.nickname',
                'a.account_type',
                'a.oprate_num',
                'b.in_storage_num',
                'a.oprate_time',
            )
                ->from('in_storage_log as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('storage as f', 'f.id', '=', 'b.storage_id')
                ->leftJoin('user as g', 'g.id', '=', 'a.oprater_id')
                ->where('a.oprater_id', $userInfo['id']);
        }

        if(!empty($startTime)) {
            $startTimeArr = explode(' ', $startTime);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($endTime)) {
            $endTimeArr = explode(' ', $endTime);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query = $query->whereBetween('a.oprate_time', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query = $query->where('a.oprate_time', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query = $query->where('a.oprate_time', '<=', $endTime);
        }

        $query = $query->whereIn('type', [0,1,6])
            ->orderBy('a.id', 'desc')
            ->paginate($pageSize,['*'], '',$currPage);

        foreach($query as $key => $value) {
            $query[$key]['oprate_time'] = date('Y-m-d H:i:s', $value['oprate_time']);
        }

        return $query;
    }

    static public function getOldOutLog($startTime, $endTime, $currPage, $pageSize, $userId, $mainId)
    {
        if($userId == $mainId) {
            $query = InStorageLogModel::select(
                'a.id',
                'a.type',
                'c.class_name as first_class_name',
                'd.class_name as second_class_name',
                'e.type_name',
                'e.materiel_name',
                'f.storage_name',
                'f.storage_address',
                'a.is_cancel',
                'g.nickname',
                'a.account_type',
                'a.oprate_num',
                'b.in_storage_num',
                'a.oprate_time',
                'h.package_name'
            )
                ->from('in_storage_log as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('storage as f', 'f.id', '=', 'b.storage_id')
                ->leftJoin('admin as g', 'g.id', '=', 'a.main_id')
                ->leftJoin('package as h', 'h.id', '=', 'a.package_id')
                ->where('a.main_id', $mainId);
        }
        else {
            $userInfo = UserModel::where('new_id', $userId)->first();

            $query = InStorageLogModel::select(
                'a.id',
                'a.type',
                'c.class_name as first_class_name',
                'd.class_name as second_class_name',
                'e.type_name',
                'e.materiel_name',
                'f.storage_name',
                'f.storage_address',
                'a.is_cancel',
                'g.nickname',
                'a.account_type',
                'a.oprate_num',
                'b.in_storage_num',
                'a.oprate_time',
                'h.package_name'
            )
                ->from('in_storage_log as a')
                ->leftJoin('storage_manage as b', 'b.id', '=', 'a.storage_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                ->leftJoin('materiel_type as e', 'e.id', '=', 'b.type_id')
                ->leftJoin('storage as f', 'f.id', '=', 'b.storage_id')
                ->leftJoin('user as g', 'g.id', '=', 'a.oprater_id')
                ->leftJoin('package as h', 'h.id', '=', 'a.package_id')
                ->where('a.oprater_id', $userInfo['id']);
        }

        if(!empty($startTime)) {
            $startTimeArr = explode(' ', $startTime);
            $startTime = strtotime($startTimeArr[0].' 00:00:00');
        }

        if(!empty($endTime)) {
            $endTimeArr = explode(' ', $endTime);
            $endTime = strtotime($endTimeArr[0].' 23:59:59');
        }

        if(!empty($startTime) && !empty($endTime)) {
            $query = $query->whereBetween('a.oprate_time', [$startTime, $endTime]);
        }
        else if(!empty($startTime) && empty($endTime)) {
            $query = $query->where('a.oprate_time', '>=', $startTime);
        }
        else if(empty($startTime) && !empty($endTime)) {
            $query = $query->where('a.oprate_time', '<=', $endTime);
        }

        $query = $query->whereIn('type', [2,3])
            ->orderBy('a.id', 'desc')
            ->paginate($pageSize,['*'], '',$currPage);

        foreach($query as $key => $value) {
            $query[$key]['package_name'] = empty($value['package_name'])?'':$value['package_name'];
            $query[$key]['oprate_time'] = date('Y-m-d H:i:s', $value['oprate_time']);
        }

        return $query;
    }

    static public function cancelOldLog($id, $userId, $mainId)
    {
        $logInfo = InStorageLogModel::where('id', $id)->first();

        if($logInfo['is_cancel']) {
            return ['code' => 1, 'msg' => '已撤销，无法重复操作', 'data' => ""];
        }

        $storageManageInfo = StorageManageModel::where('id', $logInfo['storage_id'])->where('delete_flag', 0)->first();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '库存信息不存在，无法完成撤销', 'data' => ""];
        }

        //入库撤销
        if(in_array($logInfo['type'], [0,1,6])) {
           $result = SELF::cancelOldIn($logInfo, $storageManageInfo);
        }
        //出库撤销
        else {
            $result = SELF::cancelOldOut($logInfo, $storageManageInfo);
        }

        return $result;
    }

    //旧操作记录撤销
    static public function cancelOldIn($logInfo, $storageManageInfo)
    {
        DB::beginTransaction();

        try {
            if($logInfo['oprate_num'] > $storageManageInfo['in_storage_num']) {
                return ['code' => 1, 'msg' => '库存不足，无法撤销', 'data' => ""];
            }

            if($logInfo['type'] == 6) {
                StorageManageModel::where('id', $logInfo['before_change_storage'])->increment('in_storage_num', $logInfo['oprate_num'], [
                    'delete_flag' => 0
                ]);
            }

            StorageManageModel::where('id', $storageManageInfo['id'])->decrement('in_storage_num', $logInfo['oprate_num']);
            InStorageLogModel::where('id', $logInfo['id'])->update(['is_cancel' => 1]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('旧操作记录入库撤销:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '撤销失败，请联系管理员', 'data' => ""];
        }
    }

    static public function cancelOldOut($logInfo, $storageManageInfo)
    {
        DB::beginTransaction();

        try {
            StorageManageModel::where('id', $storageManageInfo['id'])->increment('in_storage_num', $logInfo['oprate_num'], [
                'delete_flag' => 0
            ]);
            InStorageLogModel::where('id', $logInfo['id'])->update(['is_cancel' => 1]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ""];
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('旧操作记录出库库撤销:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '撤销失败，请联系管理员', 'data' => ""];
        }
    }
}
